Powershell scripts/Defender for Servers on resource level/ResourceLevelPricingAtScale.ps1 (374 lines of code) (raw):

$failureCount = 0 $successCount = 0 $vmSuccessCount = 0 $vmssSuccessCount = 0 $arcSuccessCount = 0 $vmCount = 0 $vmssCount = 0 $arcCount = 0 $vmResponseMachines = $null $vmssResponseMachines = $null $arcResponseMachines = $null # login: $needLogin = $true Try { $content = Get-AzContext if ($content) { $needLogin = ([string]::IsNullOrEmpty($content.Account)) } } Catch { if ($_ -like "*Login-AzAccount to login*") { $needLogin = $true } else { throw } } if ($needLogin) { Write-Host -ForegroundColor "yellow" "Need to log in now! Look for login window!" Connect-Azaccount } # login - end # get token $accessToken = Get-AzAccessToken | Select-Object -ExpandProperty token $expireson = Get-AzAccessToken | Select-Object -ExpandProperty expireson | Select-Object -ExpandProperty LocalDateTime # Define variables for authentication and resource group $SubscriptionId = Read-Host "Enter your SubscriptionId" $mode = Read-Host "Enter 'RG' to set pricing for all resourced under a given Resource Group, or 'TAG' to set pricing for all resources with a given tagName and tagValue" while($mode.ToLower() -ne "rg" -and $mode.ToLower() -ne "tag"){ $mode = Read-Host "Enter 'RG' to set pricing for all resources under a given Resource Group, or 'TAG' to set pricing for all resources with a given tagName and tagValue" } if ($mode.ToLower() -eq "rg") { # Fetch resources under a given Resource Group $resourceGroupName = Read-Host "Enter the name of the resource group" try { # Get all virtual machines, VMSSs, and ARC machines in the resource group $vmUrl = "https://management.azure.com/subscriptions/" + $SubscriptionId + "/resourceGroups/$resourceGroupName/providers/Microsoft.Compute/virtualMachines?api-version=2021-04-01" do{ $vmResponse = Invoke-RestMethod -Method Get -Uri $vmUrl -Headers @{Authorization = "Bearer $accessToken"} $vmResponseMachines += $vmResponse.value $vmUrl = $vmResponse.nextLink } while (![string]::IsNullOrEmpty($vmUrl)) $vmssUrl = "https://management.azure.com/subscriptions/" + $SubscriptionId + "/resourceGroups/$resourceGroupName/providers/Microsoft.Compute/virtualMachineScaleSets?api-version=2021-04-01" do{ $vmssResponse = Invoke-RestMethod -Method Get -Uri $vmssUrl -Headers @{Authorization = "Bearer $accessToken"} $vmssResponseMachines += $vmssResponse.value $vmssUrl = $vmssResponse.nextLink } while (![string]::IsNullOrEmpty($vmssUrl)) $arcUrl = "https://management.azure.com/subscriptions/" + $SubscriptionId + "/resourceGroups/$resourceGroupName/providers/Microsoft.HybridCompute/machines?api-version=2022-12-27" do{ $arcResponse = Invoke-RestMethod -Method Get -Uri $arcUrl -Headers @{Authorization = "Bearer $accessToken"} $arcResponseMachines += $arcResponse.value write-host $arcUrl $arcUrl = $arcResponse.nextLink } while (![string]::IsNullOrEmpty($arcUrl)) } catch { Write-Host "Failed to Get resources! " -ForegroundColor Red Write-Host "Response StatusCode:" $_.Exception.Response.StatusCode.value__ -ForegroundColor Red Write-Host "Response StatusDescription:" $_.Exception.Response.StatusDescription -ForegroundColor Red Write-Host "Error from response:" $_.ErrorDetails -ForegroundColor Red } } elseif ($mode.ToLower() -eq "tag") { # Fetch resources with a given tagName and tagValue $tagName = Read-Host "Enter the name of the tag" $tagValue = Read-Host "Enter the value of the tag" try { # Get all virtual machines, VMSSs, and ARC machines in the resource group based on the given tag $vmUrl = "https://management.azure.com/subscriptions/" + $SubscriptionId + "/resources?`$filter=resourceType eq 'Microsoft.Compute/virtualMachines'&api-version=2021-04-01" do{ $vmResponse = Invoke-RestMethod -Method Get -Uri $vmUrl -Headers @{Authorization = "Bearer $accessToken"} $vmResponseMachines += $vmResponse.value | where {$_.tags.$tagName -eq $tagValue} $vmUrl = $vmResponse.nextLink } while (![string]::IsNullOrEmpty($vmUrl)) $vmssUrl = "https://management.azure.com/subscriptions/" + $SubscriptionId + "/resources?`$filter=resourceType eq 'Microsoft.Compute/virtualMachineScaleSets'&api-version=2021-04-01" do{ $vmssResponse = Invoke-RestMethod -Method Get -Uri $vmssUrl -Headers @{Authorization = "Bearer $accessToken"} $vmssResponseMachines += $vmssResponse.value | where {$_.tags.$tagName -eq $tagValue} $vmssUrl = $vmssResponse.nextLink } while (![string]::IsNullOrEmpty($vmssUrl)) $arcUrl = "https://management.azure.com/subscriptions/" + $SubscriptionId + "/resources?`$filter=resourceType eq 'Microsoft.HybridCompute/machines'&api-version=2023-07-01" do{ $arcResponse = Invoke-RestMethod -Method Get -Uri $arcUrl -Headers @{Authorization = "Bearer $accessToken"} $arcResponseMachines += $arcResponse.value | where {$_.tags.$tagName -eq $tagValue} $arcUrl = $arcResponse.nextLink } while (![string]::IsNullOrEmpty($arcUrl)) } catch { Write-Host "Failed to Get resources! " -ForegroundColor Red Write-Host "Response StatusCode:" $_.Exception.Response.StatusCode.value__ -ForegroundColor Red Write-Host "Response StatusDescription:" $_.Exception.Response.StatusDescription -ForegroundColor Red Write-Host "Error from response:" $_.ErrorDetails -ForegroundColor Red } } else { Write-Host "Entered invalid mode. Exiting script." exit 1; } # Finished fetching machines, display found machines: Write-Host "Found the following resources:" -ForegroundColor Green write-host "Virtual Machines:" $count = 0 foreach ($machine in $vmResponseMachines) { $count++ Write-Host $count ": " ($machine.name) $vmCount = $count } Write-Host "-------------------" write-host "Virtual Machine Scale Sets:" $count = 0 foreach ($machine in $vmssResponseMachines) { $count++ Write-Host $count ": " ($machine.name) $vmssCount = $count } Write-Host "-------------------" write-host "ARC Machines:" $count = 0 foreach ($machine in $arcResponseMachines) { $count++ Write-Host $count ": " ($machine.name) $arcCount = $count } Write-Host "-----------------------------------------------------------------------" write-host "`n" $continue = Read-Host "Press any key to proceed or press 'N' to exit" if ($continue.ToLower() -eq "n") { exit 0 } Write-Host "-------------------" $PricingTier = Read-Host "Enter the command set these resources - 'Free' or 'Standard' or 'Delete' or 'Read' (choosing 'Free' will remove the Defender protection; 'Standard' will enable the 'P1' subplan; 'Delete' will remove any explicitly set configuration (the resource will inherit the parent's configuration); 'Read' will read the current configuration)" while($PricingTier.ToLower() -ne "free" -and $PricingTier.ToLower() -ne "standard" -and $PricingTier.ToLower() -ne "delete" -and $PricingTier.ToLower() -ne "read"){ $PricingTier = Read-Host "Enter the command for these resources - 'Free' or 'Standard' or 'Delete' or 'Read' (choosing 'Free' will remove the Defender protection; 'Standard' will enable the 'P1' subplan; 'Delete' will remove any explicitly set configuration (the resource will inherit the parent's configuration); 'Read' will read the current configuration)" } # Loop through each machine and update the pricing configuration write-host "`n" Write-Host "-------------------" Write-Host "Processing (setting or reading) Virtual Machines:" foreach ($machine in $vmResponseMachines) { # Check if need to renew the token $currentTime = Get-Date Write-host "Token expires on: $expireson - currentTime: $currentTime" if ((get-date $currentTime) -ge (get-date $expireson)) { Start-Sleep -Seconds 2 Write-host "Token expired - refreshing token:" $accessToken = Get-AzAccessToken | Select-Object -ExpandProperty token $expireson = Get-AzAccessToken | Select-Object -ExpandProperty expireson | Select-Object -ExpandProperty LocalDateTime Write-host "New token expires on: $expireson - currentTime: $currentTime - New Token is: $accessToken" } $pricingUrl = "https://management.azure.com$($machine.id)/providers/Microsoft.Security/pricings/virtualMachines?api-version=2024-01-01" if($PricingTier.ToLower() -eq "free") { $pricingBody = @{ "properties" = @{ "pricingTier" = $PricingTier } } } else { $subplan = "P1" $pricingBody = @{ "properties" = @{ "pricingTier" = $PricingTier "subPlan" = $subplan } } } Write-Host "Processing (setting or reading) pricing configuration for '$($machine.name)':" try { if($PricingTier.ToLower() -eq "delete") { $pricingResponse = Invoke-RestMethod -Method Delete -Uri $pricingUrl -Headers @{Authorization = "Bearer $accessToken"} -ContentType "application/json" -TimeoutSec 120 Write-Host "Successfully deleted pricing configuration for $($machine.name)" -ForegroundColor Green $successCount++ $vmSuccessCount++ } elseif ($PricingTier.ToLower() -eq "read") { $pricingResponse = Invoke-RestMethod -Method Get -Uri $pricingUrl -Headers @{Authorization = "Bearer $accessToken"} -ContentType "application/json" -TimeoutSec 120 Write-Host "Successfully read pricing configuration for $($machine.name): " -ForegroundColor Green Write-Host ($pricingResponse | ConvertTo-Json -Depth 100) $successCount++ $vmSuccessCount++ } else { $pricingResponse = Invoke-RestMethod -Method Put -Uri $pricingUrl -Headers @{Authorization = "Bearer $accessToken"} -Body ($pricingBody | ConvertTo-Json) -ContentType "application/json" -TimeoutSec 120 Write-Host "Successfully updated pricing configuration for $($machine.name)" -ForegroundColor Green $successCount++ $vmSuccessCount++ } } catch { $failureCount++ Write-Host "Failed to update pricing configuration for $($machine.name)" -ForegroundColor Red Write-Host "Response StatusCode:" $_.Exception.Response.StatusCode.value__ -ForegroundColor Red Write-Host "Response StatusDescription:" $_.Exception.Response.StatusDescription -ForegroundColor Red Write-Host "Error from response:" $_.ErrorDetails -ForegroundColor Red } write-host "`n" Start-Sleep -Seconds 0.3 } Write-Host "-------------------" Write-Host "Processing (setting or reading) Virtual Machine Scale Sets:" foreach ($machine in $vmssResponseMachines) { # Check if need to renew the token $currentTime = Get-Date Write-host "Token expires on: $expireson - currentTime: $currentTime" if ((get-date $currentTime) -ge (get-date $expireson)) { Start-Sleep -Seconds 2 Write-host "Token expired - refreshing token:" $accessToken = Get-AzAccessToken | Select-Object -ExpandProperty token $expireson = Get-AzAccessToken | Select-Object -ExpandProperty expireson | Select-Object -ExpandProperty LocalDateTime Write-host "New token expires on: $expireson - currentTime: $currentTime - New Token is: $accessToken" } $pricingUrl = "https://management.azure.com$($machine.id)/providers/Microsoft.Security/pricings/virtualMachines?api-version=2024-01-01" if($PricingTier.ToLower() -eq "free") { $pricingBody = @{ "properties" = @{ "pricingTier" = $PricingTier } } } else { $subplan = "P1" $pricingBody = @{ "properties" = @{ "pricingTier" = $PricingTier "subPlan" = $subplan } } } Write-Host "Processing (setting or reading) pricing configuration for '$($machine.name)':" try { if($PricingTier.ToLower() -eq "delete") { $pricingResponse = Invoke-RestMethod -Method Delete -Uri $pricingUrl -Headers @{Authorization = "Bearer $accessToken"} -ContentType "application/json" -TimeoutSec 120 Write-Host "Successfully deleted pricing configuration for $($machine.name)" -ForegroundColor Green $successCount++ $vmssSuccessCount++ } elseif ($PricingTier.ToLower() -eq "read") { $pricingResponse = Invoke-RestMethod -Method Get -Uri $pricingUrl -Headers @{Authorization = "Bearer $accessToken"} -ContentType "application/json" -TimeoutSec 120 Write-Host "Successfully read pricing configuration for $($machine.name): " -ForegroundColor Green Write-Host ($pricingResponse | ConvertTo-Json -Depth 100) $successCount++ $vmssSuccessCount++ } else { $pricingResponse = Invoke-RestMethod -Method Put -Uri $pricingUrl -Headers @{Authorization = "Bearer $accessToken"} -Body ($pricingBody | ConvertTo-Json) -ContentType "application/json" -TimeoutSec 120 Write-Host "Successfully updated pricing configuration for $($machine.name)" -ForegroundColor Green $successCount++ $vmssSuccessCount++ } } catch { $failureCount++ Write-Host "Failed to update pricing configuration for $($machine.name)" -ForegroundColor Red Write-Host "Response StatusCode:" $_.Exception.Response.StatusCode.value__ -ForegroundColor Red Write-Host "Response StatusDescription:" $_.Exception.Response.StatusDescription -ForegroundColor Red Write-Host "Error from response:" $_.ErrorDetails -ForegroundColor Red } write-host "`n" Start-Sleep -Seconds 0.3 } Write-Host "-------------------" Write-Host "Processing (setting or reading) ARC Machine:" foreach ($machine in $arcResponseMachines) { # Check if need to renew the token $currentTime = Get-Date Write-host "Token expires on: $expireson - currentTime: $currentTime" if ((get-date $currentTime) -ge (get-date $expireson)) { Start-Sleep -Seconds 2 Write-host "Token expired - refreshing token:" $accessToken = Get-AzAccessToken | Select-Object -ExpandProperty token $expireson = Get-AzAccessToken | Select-Object -ExpandProperty expireson | Select-Object -ExpandProperty LocalDateTime Write-host "New token expires on: $expireson - currentTime: $currentTime - New Token is: $accessToken" } $pricingUrl = "https://management.azure.com$($machine.id)/providers/Microsoft.Security/pricings/virtualMachines?api-version=2024-01-01" if($PricingTier.ToLower() -eq "free") { $pricingBody = @{ "properties" = @{ "pricingTier" = $PricingTier } } } else { $subplan = "P1" $pricingBody = @{ "properties" = @{ "pricingTier" = $PricingTier "subPlan" = $subplan } } } Write-Host "Processing (setting or reading) pricing configuration for '$($machine.name)':" try { if($PricingTier.ToLower() -eq "delete") { $pricingResponse = Invoke-RestMethod -Method Delete -Uri $pricingUrl -Headers @{Authorization = "Bearer $accessToken"} -ContentType "application/json" -TimeoutSec 120 Write-Host "Successfully deleted pricing configuration for $($machine.name)" -ForegroundColor Green $successCount++ $arcSuccessCount++ } elseif ($PricingTier.ToLower() -eq "read") { $pricingResponse = Invoke-RestMethod -Method Get -Uri $pricingUrl -Headers @{Authorization = "Bearer $accessToken"} -ContentType "application/json" -TimeoutSec 120 Write-Host "Successfully read pricing configuration for $($machine.name): " -ForegroundColor Green Write-Host ($pricingResponse | ConvertTo-Json -Depth 100) $successCount++ $arcSuccessCount++ } else { $pricingResponse = Invoke-RestMethod -Method Put -Uri $pricingUrl -Headers @{Authorization = "Bearer $accessToken"} -Body ($pricingBody | ConvertTo-Json) -ContentType "application/json" -TimeoutSec 120 Write-Host "Successfully updated pricing configuration for $($machine.name)" -ForegroundColor Green $successCount++ $arcSuccessCount++ } } catch { $failureCount++ Write-Host "Failed to update pricing configuration for $($machine.name)" -ForegroundColor Red Write-Host "Response StatusCode:" $_.Exception.Response.StatusCode.value__ -ForegroundColor Red Write-Host "Response StatusDescription:" $_.Exception.Response.StatusDescription -ForegroundColor Red Write-Host "Error from response:" $_.ErrorDetails -ForegroundColor Red } write-host "`n" Start-Sleep -Seconds 0.3 } Write-Host "-----------------------------------------------------------------------" Write-Host "-----------------------------------------------------------------------" write-host "`n" # Write a conclusion of all what the script did Write-Host "Summary of Pricing API results:" Write-Host "-------------------" Write-Host "Found Virtual Machines count:" $vmCount Write-Host "Successfully processed (set or read) Virtual Machines count:" $vmSuccessCount -ForegroundColor Green Write-Host "Failed processing (setting or reading) Virtual Machines count:" $($vmCount - $vmSuccessCount) -ForegroundColor $(if ($($vmCount - $vmSuccessCount) -gt 0) {'Red'} else {'Green'}) write-host "`n" Write-Host "Found Virtual Machine Scale Sets count:" $vmssCount Write-Host "Successfully processed (set or read) Virtual Machine Scale Sets result:" $vmssSuccessCount -ForegroundColor Green Write-Host "Failed processing (setting or reading) Virtual Machine Scale Sets count:" $($vmssCount - $vmssSuccessCount) -ForegroundColor $(if ($($vmssCount - $vmssSuccessCount) -gt 0) {'Red'} else {'Green'}) write-host "`n" Write-Host "Found ARC machines count:" $arcCount Write-Host "Successfully processed (set or read) ARC Machines count:" $arcSuccessCount -ForegroundColor Green Write-Host "Failed processing (setting or reading) ARC Machines count:" $($arcCount - $arcSuccessCount) -ForegroundColor $(if ($($arcCount - $arcSuccessCount) -gt 0) {'Red'} else {'Green'}) write-host "`n" Write-Host "-------------------" Write-Host "Overall" Write-Host "Successfully processed (set or read) resources: $successCount" -ForegroundColor Green Write-Host "Failures processing (setting or reading) resources: $failureCount" -ForegroundColor $(if ($failureCount -gt 0) {'Red'} else {'Green'})